package org.happy.tester.hitest.support;

import com.alibaba.fastjson.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.happy.tester.common.http.CatcherClient;
import org.happy.tester.common.model.PointcutDO;
import org.happy.tester.hitest.support.annotation.Pointcut;
import org.testng.ISuite;
import org.testng.ISuiteListener;
import org.testng.ITestNGMethod;

import java.io.*;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Classname MyTestSuiteListener
 * @Description 在所有测试类执行之前标记切点和修改切点返回值，和 HiTestMethodInterceptor 作用相同
 * @Date 2020/6/23 11:47 下午
 * @Created by jc.bai
 */
@Deprecated
public class HiTestSuiteListener implements ISuiteListener {
    @Override
    public void onStart(ISuite suite) {
        List<ITestNGMethod> iTestNGMethods = suite.getAllMethods();
        Map<String, List<PointcutDO>> collectPointcutDOSMap = new HashMap<>();
        Map<String, List<Map<PointcutDO, String>>> mockResultDOMap = new HashMap<>();
        for (ITestNGMethod testNGMethod : iTestNGMethods) {
            Method method = testNGMethod.getConstructorOrMethod().getMethod();
            if (method.isAnnotationPresent(Pointcut.class)) {
                Pointcut pointcut = method.getAnnotation(Pointcut.class);
                PointcutDO pointcutDO = new PointcutDO();
                switch (pointcut.type()) {
                    case COLLECT:
                        generatePointcutDOGroupMap(collectPointcutDOSMap, pointcutDO, pointcut);
                        break;
                    case MOCK:
                        generateMockResultMap(mockResultDOMap, pointcutDO, pointcut);
                        break;
                    default:
                        break;
                }
            }
        }
        try {
            if (!collectPointcutDOSMap.isEmpty()) {
                markCollect(collectPointcutDOSMap);
            }
            if (!mockResultDOMap.isEmpty()) {
                fixMockResult(mockResultDOMap);
            }
        } catch (UnknownHostException e) {
            System.out.println("error occur : UnknownHostException");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void markCollect(Map<String, List<PointcutDO>> collectPointcutDOSMap) throws IOException {
        JSONArray pointcutList = new JSONArray();
        Map<String, Object> pointcutListMap = new HashMap<>();
        for (Map.Entry<String, List<PointcutDO>> pointcutDOGroupMap : collectPointcutDOSMap.entrySet()) {
            pointcutListMap.put("appIp", pointcutDOGroupMap.getKey());
            pointcutListMap.put("pointcutDOS", pointcutDOGroupMap.getValue());
            pointcutListMap.put("clientIp", getLocalIp());
            pointcutList.add(pointcutListMap);
        }
        CatcherClient catcherClient = new CatcherClient();
        catcherClient.markCollect(pointcutList);
    }

    private void fixMockResult(Map<String, List<Map<PointcutDO, String>>> mockResultDOMap) throws IOException {
        JSONArray mockResultList = new JSONArray();
        Map<String, Object> mockResultListMap = new HashMap<>();
        for (Map.Entry<String, List<Map<PointcutDO, String>>> mockResult : mockResultDOMap.entrySet()) {
            mockResultListMap.put("appIp", mockResult.getKey());
            mockResultListMap.put("resultList", mockResult.getValue());
            mockResultListMap.put("clientIp", getLocalIp());
            mockResultList.add(mockResultList);
        }
        CatcherClient catcherClient = new CatcherClient();
        catcherClient.fixMockResult(mockResultList);
    }

    private String getLocalIp() throws UnknownHostException {
        InetAddress address = InetAddress.getLocalHost();
        String clientIp = address.getHostAddress();
        return clientIp;
    }

    private void generatePointcutDOGroupMap(Map<String, List<PointcutDO>> collectPointcutDOSMap, PointcutDO pointcutDO, Pointcut pointcut) {
        pointcutDO.setClassName(pointcut.className());
        pointcutDO.setMethodName(pointcut.methodName());
        pointcutDO.setParamsTypeArray(pointcut.paramsTypeArray());
        if (!collectPointcutDOSMap.containsKey(pointcut.appIp())) {
            List<PointcutDO> pointcutDOList = new ArrayList<>();
            pointcutDOList.add(pointcutDO);
            collectPointcutDOSMap.put(pointcut.appIp(), pointcutDOList);
            return;
        }
        collectPointcutDOSMap.get(pointcut.appIp()).add(pointcutDO);
    }

    private void generateMockResultMap(Map<String, List<Map<PointcutDO, String>>> mockResultDOMap, PointcutDO pointcutDO, Pointcut pointcut) {
        pointcutDO.setClassName(pointcut.className());
        pointcutDO.setMethodName(pointcut.methodName());
        pointcutDO.setParamsTypeArray(pointcut.paramsTypeArray());
        String result = getMockResult(pointcut);
        Map<PointcutDO, String> resultMap = new HashMap<>();
        resultMap.put(pointcutDO, result);
        if (StringUtils.isEmpty(result)) {
            return;
        }
        if (!mockResultDOMap.containsKey(pointcut.appIp())) {
            List<Map<PointcutDO, String>> resultMapList = new ArrayList<>();
            resultMapList.add(resultMap);
            mockResultDOMap.put(pointcut.appIp(), resultMapList);
            return;
        }
        mockResultDOMap.get(pointcut.appIp()).add(resultMap);
    }

    /**
     * 先从数据库找，数据库中没有取注解中的value，value中没有从文件中读
     *
     * @return
     */
    private String getMockResult(Pointcut pointcut) {
        //getFromDB
        if (StringUtils.isEmpty(pointcut.value())) {
            String mockFile = pointcut.className().concat(pointcut.methodName());
            return readResultFromJsonFile(mockFile);
        } else {
            return pointcut.value();
        }
    }

    /**
     * 从本地文件中读取mockResult
     *
     * @param fileName className+methodName
     * @return
     */
    private String readResultFromJsonFile(String fileName) {
        String classPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        String filePath = classPath.concat(RESULT_LOCATION).concat(fileName).concat(".json");
        File file = new File(filePath);
        String result = "";
        if (!file.exists()) {
            return result;
        }
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            isr = new InputStreamReader(new FileInputStream(file), "utf-8");
            br = new BufferedReader(isr);
            String next = "";
            while ((next = br.readLine()) != null) {
                result = result.concat(next.trim());
            }
            return result;
        } catch (FileNotFoundException | UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    private static final String RESULT_LOCATION = "json" + File.separator + "result" + File.separator;

    public static void main(String[] args) throws IOException {
        /*String str = "{\"del\":\"\"}";
        JSONObject jsonObject = JSON.parseObject(str);
        List<String> list = jsonObject.getObject(str, List.class);
        System.out.println(list);*/
        /*String strArr = "[{\"appIp\":\"192.168.0.1\",\"clientIp\":\"192.168.0.1\",\"pointcutList\":[{\"className\":\"org.mrbai.test1\",\"methodName\":\"methodName\",\"paramsTypeArray\":[\"java.lang.String\",\"java.util.List\"]},{\"className\":\"org.mrbai.test\",\"methodName\":\"methodName2\",\"paramsTypeArray\":[\"java.lang.String\",\"java.util.List\"]}]},{\"appIp\":\"192.168.0.1\",\"clientIp\":\"192.168.0.1\",\"pointcutList\":[{\"className\":\"org.mrbai.test1\",\"methodName\":\"methodName\",\"paramsTypeArray\":[\"java.lang.String\",\"java.util.List\"]},{\"className\":\"org.mrbai.test\",\"methodName\":\"methodName2\",\"paramsTypeArray\":[\"java.lang.String\",\"java.util.List\"]}]}]";
        String str = "{\"appIp\":\"192:168.0.1\",\"clientIp\":\"192.168.0.1\",\"pointcutList\":[{\"className\":\"org.mrbai.test1\",\"methodName\":\"methodName\",\"paramsTypeArray\":[\"java.lang.String\",\"java.util.List\"]},{\"className\":\"org.mrbai.test\",\"methodName\":\"methodName2\",\"paramsTypeArray\":[\"java.lang.String\",\"java.util.List\"]}]}";
        JSONObject jsonObject = JSONObject.parseObject(str);
        String replace = "{\"$.pointcutList[1].methodName\":\"test\"}";
        JSONObject jsonObject1 = JSONObject.parseObject(replace);
        JSONPath.set(jsonObject, "$.pointcutList[2].methodName", "aa");
        System.out.println(jsonObject.toString());*/

        /*JsonObject jsonObject = JsonParser.parseString(replace).getAsJsonObject();
        while (jsonReader.hasNext()) {
            JsonToken nexToken = jsonReader.peek();
            switch (nexToken) {
                case BEGIN_ARRAY:
                    jsonReader.beginArray();
                    break;
                case BEGIN_OBJECT:
                    jsonReader.beginObject();
                    break;
                case NAME:
                    String nextName = jsonReader.nextName();
                    String path = jsonReader.getPath();
                    if (jsonObject.has(path)) {
                    }
                    System.out.println(path);
                    System.out.println("nextName" + nextName);
                    break;
                case NUMBER:
                     jsonReader.nextInt();
                     break;
                case STRING:
                    jsonReader.nextString();
                    break;
                case BOOLEAN:
                    jsonReader.nextBoolean();
                    break;
                case END_DOCUMENT:
                    break;
                case NULL:
                    jsonReader.skipValue();
                    break;
                case END_ARRAY:
                    jsonReader.endArray();
                    break;
                case END_OBJECT:
                    jsonReader.endObject();
                    break;
            }
        }
        jsonReader.close();*/
        /*jsonReader.startObject();
        while (jsonReader.hasNext()) {
            String string = jsonReader.readString();
            System.out.println(string);
        }*/
        /*int[] a = new int[]{1, 2, 3, 4};
        int[] b = new int[]{1, 2, 3, 4};
        int[] ints = Arrays.copyOf(a, a.length + b.length);
        System.arraycopy(b, 0, ints, a.length, b.length);
        System.out.println(Arrays.toString(ints));*/
        InetAddress address = InetAddress.getLocalHost();
        String clientIp = address.getHostAddress();
        System.out.println(clientIp);
        //System.out.println(File.separator);
        Map<String, Object> param = new HashMap<>();
        param.put("appIp", "test");
        param.put("pointcutList", "test2");
        param.put("clientIp", "test3");
        /*com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject(param);
        CatcherClient catcherClient = new CatcherClient();
        catcherClient.markCollect(jsonObject);*/
        /*param.remove("appIp");
        System.out.println(param.size());
        JSONObject jsonObject = new JSONObject(param);
        Set<String> strings = jsonObject.keySet();
        for (String str : strings) {
            System.out.println(str);
        }*/

    }
}
